﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using IPC.Communication.Framework.Core.Net;

namespace IPC.Communication.Framework.Profinet.Melsec
{
    public class MelsecMcUdpServer : MelsecMcServer
    {
        private int _receiveCacheLength = 2048;
        public int ReceiveCacheLength
        {
            get { return _receiveCacheLength; }
            set { _receiveCacheLength = value; }
        }


        public MelsecMcUdpServer(bool isBinary = true)
            : base(isBinary)
        {
        }

        public override void ServerStart(int port)
        {
            if (!base.IsStarted)
            {
                StartInitialization();
                CoreSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                CoreSocket.Bind(new IPEndPoint(IPAddress.Any, port));
                RefreshReceive();
                base.IsStarted = true;
                base.Port = port;
                if (base.LogNet != null)
                {
                    base.LogNet.WriteInfo(ToString(), StringResources.Language.NetEngineStart);
                }
            }
        }

        private void RefreshReceive()
        {
            AppSession appSession = new AppSession();
            appSession.WorkSocket = CoreSocket;
            appSession.UdpEndPoint = new IPEndPoint(IPAddress.Any, 0);
            appSession.BytesContent = new byte[ReceiveCacheLength];
            CoreSocket.BeginReceiveFrom(appSession.BytesContent, 0, ReceiveCacheLength, SocketFlags.None, ref appSession.UdpEndPoint, AsyncCallback, appSession);
        }

        private void AsyncCallback(IAsyncResult ar)
        {
            AppSession appSession = ar.AsyncState as AppSession;
            if (appSession != null)
            {
                try
                {
                    int num = appSession.WorkSocket.EndReceiveFrom(ar, ref appSession.UdpEndPoint);
                    
                    {
                        RefreshReceive();
                        byte[] array = new byte[num];
                        Array.Copy(appSession.BytesContent, 0, array, 0, num);
                        byte[] array2 = null;
                        array2 = ((!base.IsBinary) ? ReadFromMcAsciiCore(array.RemoveBegin(22)) : ReadFromMcCore(array.RemoveBegin(11)));
                        if (base.LogNet != null)
                        {
                            base.LogNet.WriteDebug(ToString(), "Udp " + StringResources.Language.Receive + "：" + (base.IsBinary ? array.ToHexString(' ') : Encoding.ASCII.GetString(array)));
                        }
                        if (array2 != null)
                        {
                            appSession.WorkSocket.SendTo(array2, array2.Length, SocketFlags.None, appSession.UdpEndPoint);
                            if (base.LogNet != null)
                            {
                                base.LogNet.WriteDebug(ToString(), "Udp " + StringResources.Language.Send + "：" + (base.IsBinary ? array2.ToHexString(' ') : Encoding.ASCII.GetString(array2)));
                            }
                            RaiseDataReceived(appSession, array);
                        }
                        else
                        {
                            RemoveClient(appSession);
                        }
                    }
                }
                catch (ObjectDisposedException)
                {
                }
                catch (Exception ex2)
                {
                    if (base.LogNet != null)
                    {
                        base.LogNet.WriteException(ToString(), StringResources.Language.SocketEndReceiveException, ex2);
                    }
                    RefreshReceive();
                }
                finally
                {
                }
            }
        }

        public override string ToString()
        {
            return String.Format("MelsecMcUdpServer[{0}]", base.Port);
        }
    }
}
